﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using KaytechSoftware.Cms.Entities.Interfaces;
using KaytechSoftware.Cms.Services.Interfaces.Entity;

namespace KaytechSoftware.Cms.Services.Services.Entity
{
    public abstract class OrderedEntityBaseService<TEntity, TEntityDto> : EntityBaseService<TEntity, TEntityDto>, IOrderedEntityService<TEntityDto> where TEntity : class, IOrderedEntity, new() where TEntityDto : class, IDto
    {
        protected OrderedEntityBaseService(IUnitOfWorkService unitOfWorkService, IRepository<TEntity> entityRepository) : base(unitOfWorkService, entityRepository)
        {
        }

        protected virtual IQueryable<TEntity> LimitEntitiesForOrdering(TEntity promotedEntity)
        {
            return EntityRepository.GetAll();
        }

        public void MoveUp(long id)
        {
            using (var unitOfWork = UnitOfWorkService.Create())
            {
                var promotedEntity = GetById(id);
                var limitedEntities = LimitEntitiesForOrdering(promotedEntity);
                var order = promotedEntity.Order;
                var replacedEntity = limitedEntities.Where(e => e.Order > order).OrderBy(e => e.Order).FirstOrDefault();
                if (replacedEntity != null)
                {
                    promotedEntity.Order = replacedEntity.Order;
                    replacedEntity.Order = order;
                    EntityRepository.Edit(promotedEntity);
                    EntityRepository.Edit(replacedEntity);
                }

                unitOfWork.Commit();
            }
        }

        public void MoveDown(long id)
        {
            using (var unitOfWork = UnitOfWorkService.Create())
            {
                var promotedEntity = GetById(id);
                var limitedEntities = LimitEntitiesForOrdering(promotedEntity);
                var order = promotedEntity.Order;
                var replacedEntity = limitedEntities.Where(e => e.Order < order).OrderByDescending(e => e.Order).FirstOrDefault();
                if (replacedEntity != null)
                {
                    promotedEntity.Order = replacedEntity.Order;
                    replacedEntity.Order = order;
                    EntityRepository.Edit(promotedEntity);
                    EntityRepository.Edit(replacedEntity);
                }

                unitOfWork.Commit();
            }
        }
    }
}
